package com.ygqh.baby.service.wdtqyb.api;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.foxinmy.weixin4j.util.StringUtil;
import com.wdt.api.WdtClient;
import com.wdt.api.constant.ApiPlatform;
import com.wdt.api.request.StockOutOrderQueryTradeRequest;
import com.wdt.api.response.StockOutOrderQueryTradeResponse;
import com.ygqh.baby.ao.*;
import com.ygqh.baby.model.wdt.qyb.WdtShop;
import com.ygqh.baby.model.wdt.qyb.*;
import com.ygqh.baby.po.*;
import com.ygqh.baby.redis.RedisDao;
import com.ygqh.baby.service.*;
import com.ygqh.baby.service.wdtqyb.exception.WdtException;
import com.ygqh.baby.service.wdtqyb.http.WdtResponse;
import com.ygqh.baby.service.wdtqyb.util.WDTConfigure;
import com.ygqh.baby.utils.DateConvertUtils;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

@Component
public class WdtQybApi extends WdtQybBaseApi {
    protected final Logger logger = Logger.getLogger(this.getClass());

    @Autowired
    private YgOrderService ygOrderService;
    @Autowired
    private YgOrderLogService ygOrderLogService;
    @Autowired
    private YgSkuService ygSkuService;
    @Autowired
    private YgProductService ygProductService;
    @Autowired
    private AdminSupplierService adminSupplierService;
    @Autowired
    private YgReturnLogService ygReturnLogService;
    @Autowired
    private YgUserService ygUserService;
    @Autowired
    private RedisDao redisDao;
    @Autowired
    private WdtQybPushOrderByDetailApi wdtQybPushOrderByDetailApi;
    @Autowired
    private WdtClient wdtClient;


    @Value("${mail.to.all}")
    protected String mailToAll;
    @Value("${mail.to.js}")
    protected String mailToJS;
    @Value("${sms.isSend}")
    protected Boolean isSend;
    @Value("${production.mode}")
    protected Boolean productionMode;

    public WdtQybApi() {
        super();
    }

    public Message tradePushByOrderIds(List<Long> orderIds) {
        List<PushOrderErrorInfo> errorList = null;
        for (Long orderId : orderIds) {
            ResponseEntity result;
            try {
                YgOrder order = ygOrderService.findOrderDetailByOrderId(orderId);
                if (order.getOrderStatus().equals(OrderStatus.WaitingPay) || order.getOrderStatus().equals(OrderStatus.TradeClosed)) {
                    ygOrderLogService.addOrderLog(orderId, order.getOrderStatus(), "系统同步订单", "该订单尚未付款，或已关闭，系统不予同步");
                }
                result = wdtQybPushOrderByDetailApi.pushOrderToWdt(null, order);
                ygOrderLogService.addOrderLog(orderId, OrderStatus.WaitingSend, "系统同步订单", "ResultCode:" + result.getCode() + ";ResultMsg:" + result
                        .getMsg());
                if (result.isSuccess()) {
                    PushOrderToWdtResult pushOrderToWdtResult = (PushOrderToWdtResult) result.getData();
                    ygOrderService.updateWdtCode(pushOrderToWdtResult);
                }
            } catch (Exception e) {
                PushOrderErrorInfo errorInfo;
                if (CollectionUtils.isEmpty(errorList)) {
                    errorList = new ArrayList<>();
                }
                if (e instanceof WdtException) {
                    System.out.println(((WdtException) e).getErrorMsg());
                    errorInfo = new PushOrderErrorInfo(orderId.toString(), e.getMessage());
                } else {
                    errorInfo = new PushOrderErrorInfo(orderId.toString(), e.getMessage());
                }
                errorList.add(errorInfo);
                logger.warn("同步订单到旺店通失败===orderid :" + orderId + "" + e.getMessage());
                ygOrderLogService.addOrderLog(orderId, OrderStatus.WaitingSend, "系统同步订单", "同步订单到旺店通失败;" + e.getMessage());
                e.printStackTrace();
            }
        }

        if (CollectionUtils.isEmpty(errorList)) {
            return Message.success("成功同步订单到旺店通", null);
        }
        return Message.error("同步失败", errorList);

    }


    public WdtQybResult tradePushBatchByShop(String shopNo, List<YgOrder> orders) throws WdtException {

        ResponseEntity responseEntity = wdtQybPushOrderByDetailApi.pushOrderToWdtBatch(shopNo, orders);
        WdtQybResult wdtQybResult = buildWdtQybResult(responseEntity);
        return wdtQybResult;

    }

    private WdtQybResult buildWdtQybResult(ResponseEntity responseEntity) {
        WdtQybResult wdtQybResult = new WdtQybResult();
        if (!responseEntity.isSuccess()) {
            wdtQybResult.setCode(400);
            wdtQybResult.setMessage(responseEntity.getErrorMsg());
        } else {
            wdtQybResult.setCode(0);
            wdtQybResult.setMessage(responseEntity.getMsg());
        }
        Object data = responseEntity.getData();
        if (data instanceof PushOrderToWdtBatchResult) {
            PushOrderToWdtBatchResult result = (PushOrderToWdtBatchResult) data;
            if (result != null) {
                wdtQybResult.setPushSuccessList(result.getSuccessList());
                wdtQybResult.setPushErrorList(result.getErrorList());
            }
        } else if (data instanceof PushOrderToWdtResult) {
            PushOrderToWdtResult result = (PushOrderToWdtResult) data;
            List<PushOrderToWdtResult> resultList = Collections.singletonList(result);
            if (!responseEntity.isSuccess()) {
                wdtQybResult.setPushErrorList(resultList);
            } else {
                wdtQybResult.setPushSuccessList(resultList);
            }
        }
        return wdtQybResult;
    }

    public WdtQybResult tradePushBatch(List<YgOrder> orders) throws WdtException {
        return tradePushBatchByShop(null, orders);
    }


    /**
     * @param order
     * @param
     * @param WdtException 入参
     * @return WdtQybResult 返回类型
     * @throws @date 2017年6月23日 上午10:21:42
     * @Title: tradePush
     * @author （guohao）
     * @version V1.0
     */
    public WdtQybResult tradePush(YgOrder order) throws WdtException {
        String shopNo = getShopNo();
        ResponseEntity responseEntity = wdtQybPushOrderByDetailApi.pushOrderToWdt(shopNo, order);
        WdtQybResult wdtQybResult = buildWdtQybResult(responseEntity);
        return wdtQybResult;
    }

    /**
     * 申请退款
     *
     * @param returnCode
     * @return WdtQybResult 返回类型
     * @throws WdtException 入参
     * @throws @date        2017年6月21日 下午2:57:34
     * @Title: applyRefund
     * @Description: 申请退款
     * @author （guohao）
     * @version V1.0
     */
    public WdtQybResult applyRefund(YgReturnOrder returnOrder, Boolean sendStatus) throws WdtException {

        if (sendStatus) {
            return new WdtQybResult(0, "已发货走售后");
        }
        YgOrder order = ygOrderService.findOrderDetailByOrderId(returnOrder.getOrderId());

        List<YgOrderDetail> orderDetail1 = order.getOrderDetail();

        List<Long> sourceSkuIds = returnOrder.getReturnOrderDetails().stream().map(YgReturnOrderDetail::getSourceSkuId).collect(Collectors.toList());
        List<YgOrderDetail> pushList = orderDetail1.stream().filter(od -> StringUtil.isNotBlank(od.getOutCode()) && sourceSkuIds.contains(od.getSkuId())).collect(Collectors.toList());
        pushList.stream().forEach(od -> od.setRefundStatus(RefundStatus.ApplyRefund));
        Map<String, List<YgOrderDetail>> collect = pushList.stream().collect(Collectors.groupingBy(YgOrderDetail::getOutCode));

        List<YgOrder> orderList = new ArrayList<>();
        for (Map.Entry<String, List<YgOrderDetail>> entry : collect.entrySet()) {
            List<YgOrderDetail> value = entry.getValue();
            YgOrder clone = order.clone();
            clone.setOrderDetail(value);
            orderList.add(clone);
        }
        ygReturnLogService.addReturnLog(returnOrder.getReturnCode(), returnOrder.getOrderId(), "申请退款", "applyRefund", JSON.toJSONString(orderList));

        ResponseEntity responseEntity = wdtQybPushOrderByDetailApi.pushOrderToWdtBatch(getShopNo(), orderList);

        ygReturnLogService.addReturnLog(returnOrder.getReturnCode(), returnOrder.getOrderId(), "申请退款", "applyRefund", "【返回值：】" + JSON.toJSONString(responseEntity));

        WdtQybResult wdtQybResult = buildWdtQybResult(responseEntity);
        return wdtQybResult;
    }

    /**
     * ]订单查询 (根据修改时间,分页查询)
     *
     * @param status         必选项 订单状态 0 所有订单 5已取消 10待付款 15等未付16延时审核 19预订单前处理
     *                       20前处理21委外前处理22抢单前处理 25预订单 27待抢单 30待客审 35待财审 40待递交仓库 45递交仓库中
     *                       50已递交仓库 53未确认 55已确认 95已发货 100已签收 105部分打款 110已完成
     * @param startTime      必传项 查询起始时间,格式 年-月-日 时:分:秒
     * @param endTime        必选项 查询结束时间,格式同上
     * @param pageNo         必选项 分页查询的页码，从0开始
     * @param pageSize       必选项 分页大小，最大100，默认40
     * @param warehouseNo    仓库编号
     * @param imgUrl         货品信息是否返回图片url，0不返回,1返回
     * @param tradeNo        订单编号
     * @param shopNo         店铺编号
     * @param goodstax       0 使用订单中的税率 1 使用单品中的税率
     * @param hasLogisticsNo 0 没有任何限制(默认值) 1 物流单号不为空才返回 2 只返回物流单号为空的
     * @param src            1 返回订单的交易流水单号 0 不返回
     * @throws WdtException
     */
    public WdtQybResult tradeQuery(int status, Date startTime, Date endTime, int pageNo, int pageSize, String warehouseNo, int imgUrl, String tradeNo, String
            shopNo, int goodstax, int hasLogisticsNo, int src) throws WdtException {
        Map<String, String> param = getApplicationParam();

        param.put("status", status + "");
        param.put("start_time", DateConvertUtils.formatDateTime(startTime));
        param.put("end_time", DateConvertUtils.formatDateTime(endTime));
        param.put("page_no", pageNo + "");
        param.put("page_size", pageSize + "");
        if (StringUtil.isNotBlank(warehouseNo)) {
            param.put("warehouse_no", warehouseNo);
        }
        param.put("img_url", imgUrl + "");
        if (StringUtil.isNotBlank(shopNo)) {
            param.put("shop_no", shopNo);
        }
        param.put("goodstax", goodstax + "");
        param.put("has_logistics_no", hasLogisticsNo + "");
        param.put("src", src + "");
        if (StringUtil.isNotBlank(tradeNo)) {
            param.put("trade_no", tradeNo + "");
        }

        String sign = getSign(param);
        param.put("sign", sign);
        System.out.println(param.toString());

        String apiUri = getRequestUri("trade_query_uri");
        /*
         * try { String post = HttpUtil.post(apiUri, new HashMap<String,
         * Object>(param)); } catch (IOException e) { catch block
         * e.printStackTrace(); }
         */
        WdtResponse response = wdtRequestExecutor.post(apiUri, param);
        System.out.println(response.getAsString());
        return response.getAsObject(new TypeReference<WdtQybResult>() {
        });

    }

    public WdtQybResult tradeQuery(int status, Date startTime, Date endTime, int pageNo) throws WdtException {
        return this.tradeQuery(status, startTime, endTime, pageNo, 40, null, 0, null, getRequestUri(WDTConfigure.SHOP_NO), 0, 0, 1);
    }

    public WdtQybResult tradeQuery(int status, String shopNo, Date startTime, Date endTime, int pageNo) throws WdtException {
        return this.tradeQuery(status, startTime, endTime, pageNo, 40, null, 0, null, shopNo, 0, 0, 1);
    }

    public WdtQybResult tradeQuery(int status, Date startTime, Date endTime, int pageNo, String tradeNo) throws WdtException {
        return this.tradeQuery(status, startTime, endTime, pageNo, 40, getRequestUri(WDTConfigure.WAREHOSE_NO), 0, tradeNo, getRequestUri(WDTConfigure
                .SHOP_NO), 0, 0, 1);
    }

    /**
     * 同步库存接口
     *
     * @param limit 最多返回条数 (不可超过2000 不少于100 默认为 100)
     * @return
     * @throws WdtException
     */
    public WdtQybResult syncSkuStock(int limit) throws WdtException {
        Map<String, String> param = getApplicationParam();
        param.put("limit", limit + "");
        param.put("shop_no", getShopNo());
        String sign = getSign(param);
        param.put("sign", sign);

        String apiUri = getRequestUri("sync_stock_uri");
        WdtResponse response = wdtRequestExecutor.post(apiUri, param);
        logger.info(response.getAsString());
        return response.getAsObject(new TypeReference<WdtQybResult>() {
        });

    }

    /**
     * 同步库存回传
     *
     * @param list
     * @return
     * @throws WdtException
     */
    public WdtQybResult syncSkuStockBack(List<WdtSkuStockBack> list) throws WdtException {
        Map<String, String> param = getApplicationParam();
        param.put("stock_sync_list", JSON.toJSONString(list));
        String sign = getSign(param);
        param.put("sign", sign);

        String apiUri = getRequestUri("sync_stock_back_uri");
        WdtResponse response = wdtRequestExecutor.post(apiUri, param);
        System.out.println(response.getAsString());

        return response.getAsObject(new TypeReference<WdtQybResult>() {
        });

    }

    /**
     * 只支持 退货和退款不退货 注意下。不能处理售前退款。
     *
     * @param returnOrder
     * @return
     * @throws WdtException
     */
    public WdtQybResult pushRefundOrder(YgReturnOrder returnOrder) throws WdtException {

        List<WdtQybRefundReq> refundList = new ArrayList<WdtQybRefundReq>();
        List<WdtRefundDetail> refundDetailList = new ArrayList<WdtRefundDetail>();
        YgOrder order = ygOrderService.findOrderDetailByOrderId(returnOrder.getOrderId());

        order.getOrderDetail().forEach(od -> {

            returnOrder.getReturnOrderDetails().forEach(rod -> {
                WdtRefundDetail detail = new WdtRefundDetail(od.getId().toString(), new BigDecimal(rod.getAmount()));
                refundDetailList.add(detail);
            });
        });
        WdtQybRefundReq refund = new WdtQybRefundReq(returnOrder.getOrderId().toString(), returnOrder.getReturnCode(), 3, "goods_returning", returnOrder
                .getReturnPrice().toString(), order.getReceiver(), returnOrder.getCreateTime(), returnOrder.getRemark(), returnOrder.getRemark(),
                getRequestUri(WDTConfigure.SHOP_NO), refundDetailList);
        refundList.add(refund);

        Map<String, String> param = getApplicationParam();
        param.put("api_refund_list", JSON.toJSONString(refundList));
        String sign = getSign(param);
        param.put("sign", sign);

        String apiUri = getRequestUri("push_refund_uri");
        WdtResponse response = wdtRequestExecutor.post(apiUri, param);

        return response.getAsObject(new TypeReference<WdtQybResult>() {
        });

    }

    /**
     * 推送换货单(售后)
     *
     * @param changeOrder
     * @return WdtQybResult 返回类型
     * @throws WdtException 入参
     * @throws @date        2017年6月14日 上午10:51:48
     * @Title: pushChangeOrder
     * @author （作者）
     * @version V1.0
     */
    public WdtQybResult pushChangeOrderAfter(YgReturnOrder changeOrder) throws WdtException {

        if (changeOrder.getReturnType().equals(ReturnType.Return)) {
            WdtQybResult result = new WdtQybResult(-1, "售后退货，订单不予同步。" + changeOrder.getReturnCode());
            logger.warn("售后退货，订单不予同步。" + changeOrder.getReturnCode());
            return result;
        }

        YgOrder order = ygOrderService.findOrderDetailByOrderId(changeOrder.getOrderId());
        List<YgOrderDetail> onlyYiigoo = getOrderDetailOnlyYiigoo(order.getOrderDetail());
        if (CollectionUtils.isEmpty(onlyYiigoo)) {
            return new WdtQybResult(0, "明细为空不予同步");
        }

        final BigDecimal zero = new BigDecimal("0.0000");
        BigDecimal totalPrice = new BigDecimal("0.0000");

        ArrayList<WdtQybOrderReq> orderList = new ArrayList<WdtQybOrderReq>();
        List<WdtQybOrderLstReq> detailList = new ArrayList<WdtQybOrderLstReq>();
        // 订单明细
        for (YgOrderDetail od : onlyYiigoo) {

            for (YgReturnOrderDetail rod : changeOrder.getReturnOrderDetails()) {
                // 售后换货 只处理已发货的商品
                if (od.getSkuId().equals(rod.getSourceSkuId()) && !od.getDetailStatus().equals(OrderDetailStatus.WaitingSend)) {
                    // 换之后的商品
                    YgProduct product = ygProductService.findById(rod.getProductId());
                    totalPrice = totalPrice.add(od.getSalePrice().multiply(new BigDecimal(rod.getAmount())));
                    WdtQybOrderLstReq newLstReq = new WdtQybOrderLstReq(changeOrder.getReturnCode() + "-" + rod.getId(), new BigDecimal(rod.getAmount()), od
                            .getSalePrice(), 30, 0, product.getProductCode(), od.getProductName(), rod.getSkuCode(), product.getShortName() + " " + rod
                            .getSizeName(), "");
                    newLstReq.setShareDiscount(zero);
                    detailList.add(newLstReq);
                }

            }
        }
        ;
        // 订单主信息
        WdtQybOrderReq orderReq = new WdtQybOrderReq(changeOrder.getReturnCode(), 30, 1, "2", changeOrder.getReceiver(), changeOrder.getProvinceName(),
                changeOrder.getCityName(), changeOrder.getAreaName(), changeOrder.getAddress(), "-1", zero.toString(), "0", "0", "0", totalPrice.toString(),
                detailList);

        if (StringUtil.isBlank(order.getUserName())) {
            YgUser user = ygUserService.findById(order.getUserId());
            order.setUserName(user.getUserName());
        }
        orderReq.setBuyerNick(order.getNickName());
        orderReq.setReceiverMobile(changeOrder.getTelPhone());
        orderReq.setTradeTime(order.getCreateTime());
        orderReq.setPayTime(order.getPaidTime());

        orderList.add(orderReq);
        String orderInfo = JSON.toJSONString(orderList);
        // 系统级别参数
        Map<String, String> param = getApplicationParam();
        // 接口级别参数
        param.put("shop_no", getRequestUri(WDTConfigure.SHOP_NO));
        param.put("trade_list", orderInfo);
        // 获取签名
        String sign = getSign(param);
        param.put("sign", sign);

        // 获取api路径
        String apiUrl = getRequestUri("trade_push_uri");
        ygReturnLogService.addReturnLog(changeOrder.getReturnCode(), changeOrder.getOrderId(), "售后换货，推送订单", "pushChangeOrderAfter", param.toString());
        WdtResponse wdtResponse = wdtRequestExecutor.post(apiUrl, param);
        ygReturnLogService.addReturnLog(changeOrder.getReturnCode(), changeOrder.getOrderId(), "售后换货，推送订单", "pushChangeOrderAfter", "【返回值：】" + wdtResponse
                .getAsString());
        return wdtResponse.getAsObject(new TypeReference<WdtQybResult>() {
        });

    }

    /**
     * 推送换货单 直接推送
     *
     * @param changeOrder
     * @return WdtQybResult 返回类型
     * @throws WdtException 入参
     * @throws @date        2017年6月14日 上午10:51:48
     * @Title: pushChangeOrder
     * @author （作者）
     * @version V1.0
     */
    public WdtQybResult pushChangeOrder(YgReturnOrder changeOrder) throws WdtException {

        final BigDecimal zero = new BigDecimal("0.0000");
        BigDecimal totalPrice = new BigDecimal("0.0000");

        int tradeStatus = 30;
        ArrayList<WdtQybOrderReq> orderList = new ArrayList<WdtQybOrderReq>();
        List<WdtQybOrderLstReq> detailList = new ArrayList<WdtQybOrderLstReq>();

        // 订单明细
        for (YgReturnOrderDetail rod : changeOrder.getReturnOrderDetails()) {

            YgProduct product = ygProductService.findById(rod.getProductId());

            if (changeOrder.getReturnType().equals(ReturnType.Change)) {
                // 换货
                // 换之后的商品
                totalPrice = totalPrice.add(product.getProductSalePrice().multiply(new BigDecimal(rod.getAmount())));
                WdtQybOrderLstReq newLstReq = new WdtQybOrderLstReq(changeOrder.getReturnCode() + "-" + rod.getId(), new BigDecimal(rod.getAmount()), product
                        .getProductSalePrice(), 30, 0, product.getProductCode(), product.getProductName(), rod.getSkuCode(), product.getShortName() + " " +
                        rod.getSizeName(), "");
                newLstReq.setShareDiscount(zero);
                detailList.add(newLstReq);

            }
        }
        if (CollectionUtils.isEmpty(detailList)) {
            return new WdtQybResult(-1, "需要退换的明细为空，不予同步。" + changeOrder.getReturnCode());
        }

        // 订单主信息
        WdtQybOrderReq orderReq = new WdtQybOrderReq(changeOrder.getReturnCode(), tradeStatus, 1, "2", changeOrder.getReceiver(), changeOrder.getProvinceName
                (), changeOrder.getCityName(), changeOrder.getAreaName(), changeOrder.getAddress(), "-1", zero.toString(), "0", "0", "0", totalPrice.toString
                (), detailList);
        YgUser user = ygUserService.findById(changeOrder.getUserId());
        orderReq.setBuyerNick(user.getUserName());
        orderReq.setReceiverMobile(changeOrder.getTelPhone());
        orderReq.setTradeTime(changeOrder.getCreateTime());
        orderReq.setPayTime(new Date());

        orderList.add(orderReq);
        String orderInfo = JSON.toJSONString(orderList);
        // 系统级别参数
        Map<String, String> param = getApplicationParam();
        // 接口级别参数
        param.put("shop_no", getRequestUri(WDTConfigure.SHOP_NO));
        param.put("trade_list", orderInfo);
        // 获取签名
        String sign = getSign(param);
        param.put("sign", sign);

        // 获取api路径
        String apiUrl = getRequestUri("trade_push_uri");
        System.out.println(param.toString());
        WdtResponse wdtResponse = wdtRequestExecutor.post(apiUrl, param);
        System.out.println(wdtResponse.getAsString());
        return wdtResponse.getAsObject(new TypeReference<WdtQybResult>() {
        });

    }

    public WdtQybResult pushChangeOrderBefore(YgReturnOrder changeOrder, Boolean isSend) throws WdtException {
        YgOrder order = ygOrderService.findOrderDetailByOrderId(changeOrder.getOrderId());
        if (isSend) {
            return new WdtQybResult(0, "已发货走售后");
        }
        if (order.getTotalPrice().add(order.getAccountPrice()).compareTo(changeOrder.getReturnPrice()) == 0) {
            return new WdtQybResult(0, "全部退货不予同步；");
        }
        List<YgOrderDetail> onlyYiigoo = getOrderDetailOnlyYiigoo(order.getOrderDetail());
        if (CollectionUtils.isEmpty(onlyYiigoo)) {
            return new WdtQybResult(0, "明细为空不予同步；");
        }
        final BigDecimal zero = new BigDecimal("0.0000");
        BigDecimal totalPrice = new BigDecimal("0.0000");

        int tradeStatus = 30;
        ArrayList<WdtQybOrderReq> orderList = new ArrayList<WdtQybOrderReq>();
        List<WdtQybOrderLstReq> detailList = new ArrayList<WdtQybOrderLstReq>();

        List<YgOrderDetail> hasReturnDetails = new ArrayList<YgOrderDetail>();

        List<Long> sourceSkuIds = new ArrayList<Long>();
        // 订单明细
        for (YgOrderDetail od : onlyYiigoo) {
            for (YgReturnOrderDetail rod : changeOrder.getReturnOrderDetails()) {
                if (od.getSkuId().equals(rod.getSourceSkuId())) {

                    if (!sourceSkuIds.contains(rod.getSourceSkuId())) {
                        hasReturnDetails.add(od);
                    }
                    Long lastAmount = od.getQuantity() - rod.getAmount();
                    // 已发货的商品走售后退货流程
                    // 这里不再验证，通过传参判断是否发货


                    YgProduct product = ygProductService.findById(rod.getProductId());

                    od.setProductId(product.getId());
                    od.setProductCode(product.getProductCode());

                    if (changeOrder.getReturnType().equals(ReturnType.Change)) {
                        // 换货
                        // 换之后的商品
                        totalPrice = totalPrice.add(od.getSalePrice().multiply(new BigDecimal(rod.getAmount())));
                        WdtQybOrderLstReq newLstReq = new WdtQybOrderLstReq(changeOrder.getReturnCode() + "-" + rod.getId(), new BigDecimal(rod.getAmount()),
                                od.getSalePrice(), 30, 0, product.getProductCode(), od.getProductName(), rod.getSkuCode(), product.getShortName() + " " + rod
                                .getSizeName(), "");
                        newLstReq.setShareDiscount(zero);
                        detailList.add(newLstReq);

                    }
                    od.setQuantity(lastAmount);

                }
            }
        }
        for (YgOrderDetail od : hasReturnDetails) {
            // 判断退换之前的商品购买数量
            // 如果大于退换货件数的话，需要将剩下的数量推送到旺店通
            if (od.getQuantity() > 0) {

                WdtQybOrderLstReq oldLstReq = new WdtQybOrderLstReq(changeOrder.getReturnCode() + "-" + od.getId() + "-" + order.getId(), new BigDecimal(od
                        .getQuantity()), od.getSalePrice(), 30, 0, od.getProductCode(), od.getProductName(), od.getSkuCode(), od.getShortName() + " " + od
                        .getSize(), "");
                oldLstReq.setShareDiscount(od.getSalePrice().multiply(new BigDecimal(od.getQuantity())));
                detailList.add(oldLstReq);

            }
        }
        if (CollectionUtils.isEmpty(detailList)) {
            ygReturnLogService.addReturnLog(changeOrder.getReturnCode(), changeOrder.getOrderId(), "需要退换的明细为空，不予同步。", "pushChangeOrderBefore", "");
            return new WdtQybResult(0, "需要退换的明细为空，不予同步。" + changeOrder.getReturnCode());
        }

        // 订单主信息
        WdtQybOrderReq orderReq = new WdtQybOrderReq(changeOrder.getReturnCode(), tradeStatus, 1, "2", order.getReceiver(), order.getProvinceName(), order
                .getCityName(), order.getAreaName(), order.getAddress(), "-1", zero.toString(), "0", "0", "0", totalPrice.toString(), detailList);
        if (StringUtil.isBlank(order.getUserName())) {
            YgUser user = ygUserService.findById(order.getUserId());
            order.setUserName(user.getUserName());
        }
        orderReq.setBuyerNick(order.getUserName());
        orderReq.setReceiverMobile(order.getTelPhone());
        orderReq.setTradeTime(order.getCreateTime());
        orderReq.setPayTime(order.getPaidTime());

        orderList.add(orderReq);
        String orderInfo = JSON.toJSONString(orderList);
        // 系统级别参数
        Map<String, String> param = getApplicationParam();
        // 接口级别参数
        param.put("shop_no", getRequestUri(WDTConfigure.SHOP_NO));
        param.put("trade_list", orderInfo);
        // 获取签名
        String sign = getSign(param);
        param.put("sign", sign);

        // 获取api路径
        String apiUrl = getRequestUri("trade_push_uri");
        WdtResponse wdtResponse = wdtRequestExecutor.post(apiUrl, param);
        ygReturnLogService.addReturnLog(changeOrder.getReturnCode(), changeOrder.getOrderId(), "售前" + changeOrder.getReturnType() + "，推送订单", "", param
                .toString() + "【返回值：】" + wdtResponse.getAsString());
        return wdtResponse.getAsObject(new TypeReference<WdtQybResult>() {
        });

    }

    /**
     * 按时间区间查询入库单详细
     *
     * @param startTime
     * @param endTime
     * @param orderType 源单据类别 1,采购入库2,调拨入库3,退货入库4, 盘盈入库 5,生产入库6,其他入库
     * @param status    入库单状态
     *                  10已取消30待审核60待结算80已完成（按照状态查询时必须传原单据类别，如果未传status则默认查询80已完成单据）
     * @param pageNo    页号,默认0，从0页开始。
     * @param pageNo    分页大小（最大不超过30条，默认返回30条）
     * @return
     * @throws WdtException
     */
    public WdtQybResult queryStockIn(Date startTime, Date endTime, Integer orderType, Integer status, Integer pageNo) throws WdtException {
        Map<String, String> param = getApplicationParam();
        param.put("start_time", DateConvertUtils.formatDateTime(startTime));
        param.put("end_time", DateConvertUtils.formatDateTime(endTime));
        if (orderType != null) {
            param.put("order_type", orderType + "");
        }
        if (status != null) {
            param.put("status", status + "");
        }
        param.put("page_no", pageNo + "");
        param.put("page_size", 30 + "");
        String sign = getSign(param);
        param.put("sign", sign);
        String apiUri = getRequestUri("query_stock_in_uri");
        System.out.println("【param】：" + param);
        WdtResponse response = wdtRequestExecutor.post(apiUri, param);
        String res = response.getAsString();
        System.out.println("【result】:" + res);
        return response.getAsObject(new TypeReference<WdtQybResult>() {
        });

    }

    /**
     * 查询销售出库单
     *
     * @param startTime   开始日期，0000-00-00 0:0:0
     * @param endTime     结束日期，0000-00-00 0:0:0
     * @param status      55已审核,5,已取消 (此参数查询时间为最后更新时间)，不传此参数默认按照出库时间查询，已发货已完成单据。
     * @param warehouseNo 仓库编号
     * @param pageNo      页号,默认0，从0页开始。
     * @param pageNo      分页大小（最大不超过30条，默认返回30条）
     * @return
     * @throws WdtException
     */

    public WdtQybResult querySaleStockOut(Date startTime, Date endTime, Integer status, String warehouseNo, int pageNo) throws WdtException {
        Map<String, String> param = getApplicationParam();
        param.put("start_time", DateConvertUtils.formatDateTime(startTime));
        param.put("end_time", DateConvertUtils.formatDateTime(endTime));
        if (status != null) {
            param.put("status", status + "");
        }
        param.put("page_no", pageNo + "");
        param.put("page_size", 30 + "");
        if (StringUtil.isNotBlank(warehouseNo)) {
            param.put("warehouse_no", warehouseNo);
        }

        String sign = getSign(param);
        param.put("sign", sign);
        String apiUri = getRequestUri("query_sale_stock_out_uri");
        WdtResponse response = wdtRequestExecutor.post(apiUri, param);
        String res = response.getAsString();
        System.out.println(param);
        System.out.println(res);
        return response.getAsObject(new TypeReference<WdtQybResult>() {
        });

    }

    public StockOutOrderQueryTradeResponse querySaleStockOut(Date startTime, Date endTime, Integer status, String warehouseNo, Boolean isTaoBao) throws com.wdt.api.exception.WdtException {

        StockOutOrderQueryTradeRequest request = new StockOutOrderQueryTradeRequest();

        request.setStartTime(startTime);
        request.setEndTime(endTime);
        request.setStatus(status);
        request.setWarehouseNo(warehouseNo);
        if (isTaoBao) {
            request.setApiPlatform(ApiPlatform.QiMen);
        }
        return wdtClient.executeQuery(request);
    }

    /**
     * 查询出库单管理
     *
     * @param startTime   开始日期，0000-00-00 0:0:0
     * @param endTime     结束日期，0000-00-00 0:0:0
     * @param orderType   出库单类型（1销售订单2,调拨出库3,采购退货出库4,盘亏出库5, 生产出库6现款销售出库7,其他出库）
     * @param warehouseNo 仓库编号
     * @param srcOrderNo  源单号
     * @param pageNo      页号,默认0，从0页开始。
     * @param pageNo      分页大小（最大不超过30条，默认返回30条）
     * @return
     * @throws WdtException
     */
    public WdtQybResult queryStockOut(Date startTime, Date endTime, Integer orderType, String srcOrderNo, String warehouseNo, int pageNo) throws WdtException {
        Map<String, String> param = getApplicationParam();
        param.put("start_time", DateConvertUtils.formatDateTime(startTime));
        param.put("end_time", DateConvertUtils.formatDateTime(endTime));
        if (orderType != null) {
            param.put("order_type", orderType + "");
        }
        if (StringUtil.isNotBlank(srcOrderNo)) {
            param.put("src_order_no", srcOrderNo);
        }
        param.put("page_no", pageNo + "");
        param.put("page_size", 30 + "");
        if (StringUtil.isNotBlank(warehouseNo)) {
            param.put("warehouse_no", warehouseNo);
        }

        String sign = getSign(param);
        param.put("sign", sign);
        String apiUri = getRequestUri("query_stock_out_uri");
        WdtResponse response = wdtRequestExecutor.post(apiUri, param);
        String res = response.getAsString();
        System.out.println(param);
        System.out.println(res);
        return response.getAsObject(new TypeReference<WdtQybResult>() {
        });

    }

    /**
     * 查询物流同步
     *
     * @param limit          最多返回条数(不可超过100)
     * @param isPartSyncAble 是否支持拆单发货 0 否 1 是（支持开启多物流单号回传的卖家，没有对应需求的卖家请不要传该字段）
     * @return
     * @throws WdtException
     */
    public WdtSyncLogisticsResult syncLogistics(int limit, int isPartSyncAble) throws WdtException {
        Map<String, String> param = getApplicationParam();
        param.put("limit", limit + "");
        param.put("shop_no", getRequestUri(WDTConfigure.SHOP_NO));
        param.put("is_part_sync_able", isPartSyncAble + "");
        String sign = getSign(param);
        param.put("sign", sign);
        String apiUri = getRequestUri("sync_logistics_uri");
        WdtResponse response = wdtRequestExecutor.post(apiUri, param);
        logger.info("【param】:" + param.toString());
        String res = response.getAsString();
        logger.info("【result】:" + res);
        return response.getAsObject(new TypeReference<WdtSyncLogisticsResult>() {
        });

    }

    /**
     * 物流同步状态回写(批量)
     *
     * @param backs
     * @return
     * @throws WdtException
     */
    public WdtSyncLogisticsResult syncLogisticsBack(List<WdtSyncLogisticsBack> backs) throws WdtException {
        Map<String, String> param = getApplicationParam();
        param.put("logistics_list", JSON.toJSONString(backs));
        String sign = getSign(param);
        param.put("sign", sign);
        String apiUri = getRequestUri("sync_logistics_back_uri");
        WdtResponse response = wdtRequestExecutor.post(apiUri, param);
        logger.info("【param】:" + param.toString());
        String res = response.getAsString();
        logger.info("【result】:" + res);
        return response.getAsObject(new TypeReference<WdtSyncLogisticsResult>() {
        });

    }

    /**
     * 采购单
     *
     * @param purchase
     * @return
     * @throws WdtException
     */
    public WdtQybResult purchasePush(AdminPurchase purchase) throws WdtException {
        Map<String, String> param = getApplicationParam();

        List<WdtPurchaseReq> list = new ArrayList<WdtPurchaseReq>();
        List<WdtPurchaseDetailReq> detailsList = new ArrayList<WdtPurchaseDetailReq>();

        List<AdminPurchaseDetail> purchaseDetail = purchase.getPurchaseDetail();
        for (AdminPurchaseDetail detail : purchaseDetail) {
            WdtPurchaseDetailReq detailReq = new WdtPurchaseDetailReq(detail.getSkuCode(), detail.getQuantity().toString(), new BigDecimal(100));
            detailsList.add(detailReq);
        }
        AdminSupplier supplier = adminSupplierService.findById(purchase.getSupplierId());
        WdtPurchaseReq purchaseReq = new WdtPurchaseReq(supplier.getSupplierNo(), purchase.getPurchaseCode(), getRequestUri(WDTConfigure.WAREHOSE_NO),
                DateConvertUtils.format(purchase.getPreArriveDate(), DateConvertUtils.DATE_TIME_FORMAT), detailsList);

        list.add(purchaseReq);
        param.put("purchase_info", JSON.toJSONString(purchaseReq));
        String sign = getSign(param);
        param.put("sign", sign);
        String apiUri = getRequestUri("purchase_push_uri");
        System.out.println(param.toString());
        /*
         * try { String post = HttpUtil.post(apiUri, new HashMap<String,
         * Object>(param)); } catch (IOException e) { catch block
         * e.printStackTrace(); }
         */
        WdtResponse response = wdtRequestExecutor.post(apiUri, param);
        String res = response.getAsString();
        System.out.println(res);
        return response.getAsObject(new TypeReference<WdtQybResult>() {
        });

    }

    /**
     * @param @param  purchase
     * @param @return
     * @param @throws WdtException 入参
     * @return WdtQybResult 返回类型
     * @throws @date 2017年6月13日 下午2:15:16
     * @Title: 创建平台货品
     * @Description: 外部系统推送平台货品到ERP，并根据系统配置决定是否自动匹配ERP内货品，只支持自有平台。erp中创建 货品-平台货品
     * 中的货品资料
     * @author （作者）
     * @version V1.0
     */
    public WdtQybResult goodsSpecPush(List<WdtGoosSpecPushReq> goodsList) throws WdtException {

        WdtGoodsInfo goodsInfo = new WdtGoodsInfo(127 + "", getRequestUri(WDTConfigure.SHOP_NO), goodsList);
        Map<String, String> param = getApplicationParam();
        param.put("api_goods_info", JSON.toJSONString(goodsInfo));
        String sign = getSign(param);
        param.put("sign", sign);

        System.out.println(param.toString());
        String apiUri = getRequestUri("goods_spec_push_uri");
        WdtResponse response = wdtRequestExecutor.post(apiUri, param);
        String res = response.getAsString();
        System.out.println(res);
        return response.getAsObject(new TypeReference<WdtQybResult>() {
        });

    }

    /**
     * 退换单查询(根据修改时间,分页查询)
     *
     * @param processStatus int 是 退换单处理状态 10已取消 20待审核 30已同意 40已拒绝 50待财审 60待收货 70部分到货 80待结算
     *                      90已完成
     * @param startTime     date 是 查询起始时间,格式 年-月-日 时:分:秒
     * @param endTime       date 是 查询结束时间,格式同上
     * @param pageNo        int 是 分页查询的页码，从0开始
     * @param pageSize      int 是 分页大小，最大100，默认40
     * @param refundNo      varchar 否 Erp内退换单编号
     * @param srcRefundNo   varchar 否 平台原始退换单号
     * @return WdtQybResult 返回类型
     * @throws WdtException 入参
     * @throws @date        2017年9月26日 下午3:13:19
     * @Title: refundQuery
     * @author （guohao）
     * @version V1.0
     */

    public WdtQybResult refundQuery(int processStatus, Date startTime, Date endTime, int pageNo, int pageSize, String refundNo, String srcRefundNo) throws
            WdtException {

        Map<String, String> param = getApplicationParam();
        param.put("process_status", processStatus + "");
        param.put("start_time", DateConvertUtils.formatDateTime(startTime));
        param.put("end_time", DateConvertUtils.formatDateTime(endTime));
        param.put("page_no", pageNo + "");
        param.put("page_size", pageSize + "");
        if (!StringUtil.isEmpty(refundNo)) {
            param.put("refund_no", refundNo);
        }
        if (!StringUtil.isEmpty(srcRefundNo)) {
            param.put("src_refund_no", srcRefundNo);
        }
        String sign = getSign(param);
        param.put("sign", sign);

        System.out.println(param.toString());
        String apiUri = getRequestUri("refund_query_uri");
        WdtResponse response = wdtRequestExecutor.post(apiUri, param);
        String res = response.getAsString();
        System.out.println(res);
        return response.getAsObject(new TypeReference<WdtQybResult>() {
        });

    }

    public WdtQybResult queryShop(String shopNo, Integer platformId, int pageSize, int pageNo) throws WdtException {
        Map<String, String> param = getApplicationParam();
        if (StringUtil.isNotBlank(shopNo)) {
            param.put("shop_no", shopNo);
        }
        if (platformId != null) {
            param.put("platform", platformId.toString());
        }
        param.put("page_no", pageNo + "");
        param.put("page_size", pageSize + "");
        String sign = getSign(param);
        param.put("sign", sign);
        String apiUri = getRequestUri("shop_query_uri");
        WdtResponse response = wdtRequestExecutor.post(apiUri, param);
        String res = response.getAsString();
        System.out.println(res);
        return response.getAsObject(new TypeReference<WdtQybResult>() {
        });
    }

    private final static String WDT_SHOP_KEY = "wdt_all_shop";

    public List<WdtShop> getAllShop() {
        try {
            String s = redisDao.get(WDT_SHOP_KEY);
            WdtQybResult wdtQybResult = this.queryShop(null, null, 0, 0);
            if (StringUtil.isNotBlank(s)) {
                List<WdtShop> wdtShops = JSON.parseArray(s, WdtShop.class);

                if (!productionMode || wdtShops.size() == wdtQybResult.getTotalCount()) {
                    return wdtShops;
                } else {
                    return doGetAllShop(wdtQybResult.getTotalCount());
                }

            } else {
                return doGetAllShop(wdtQybResult.getTotalCount());
            }
        } catch (WdtException e) {
            e.printStackTrace();
        }
        return Collections.emptyList();
    }

    private List<WdtShop> doGetAllShop(int totalCount) throws WdtException {
        Double ceil = Math.ceil((double) totalCount / 30);
        int pageCout = ceil.intValue();
        List<WdtShop> shopList = new ArrayList<>();
        while (pageCout >= 0) {

            WdtQybResult wdtQybResult = this.queryShop(null, null, 30, pageCout);
            --pageCout;
            shopList.addAll(wdtQybResult.getShoplist());
        }
        redisDao.set(WDT_SHOP_KEY, JSON.toJSONString(shopList), 0);
        return shopList;
    }


}
